/*
   Project AwesOmeScript
   Copyright 2010 Domenico Gentner

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "stdafx.hpp"
#include "Viewbase.hpp"
#include "Notebookview.hpp"
#include "Splitview.hpp"
#include "ProjectManager.hpp"
#include "Application.hpp"
#include "SettingsDialog.hpp"
#include "NewProjectDialog.hpp"
#include "ProjectPropertiesDialog.hpp"
#include "IconBrowser.hpp"
#include "ProjectManager.hpp"
#include "Helpers.hpp"
#include "Mainframe.hpp"


// Defines are evil, so we use some global consts
const wxString ASS_STARTUP_FILE("html/startup");
const Version ASS_VERSION(0, 4, 0);
const wxString ASS_LABEL(wxString("AwesOme Script ") + ASS_VERSION);
const wxString ASS_STATIC_SCRIPT_TEXT("<a href=\"text\"://></a>");
const int ASS_MAX_SCRIPT_LENGTH=1024;

//////////////////////////////////////////////////////////////////////////
// Curl Callback
static size_t my_curl_write( void *ptr, size_t size, size_t nmemb, void *stream)
{
	if ( stream != NULL )
	{
		Mainframe* frame = static_cast<Mainframe*>(stream);
		wxString b((char*)ptr);
		frame->TellVersion(b);
	}
	return size*nmemb;;
}


//////////////////////////////////////////////////////////////////////////
// Event Table
BEGIN_EVENT_TABLE(Mainframe, wxFrame)
	EVT_MENU(idMENU_RELOAD_HTML,		Mainframe::OnReloadHtml)
	EVT_MENU(idMENU_SHOW_STARTUP,		Mainframe::OnShowStartup)
	EVT_MENU(idMENU_ABOUT,				Mainframe::OnAbout)
	EVT_MENU(idMENU_EXIT,				Mainframe::OnExit)
	EVT_MENU(idMENU_NOTEBOOKVIEW,		Mainframe::OnCheckNotebookView)
	EVT_MENU(idMENU_SPLITVIEW,			Mainframe::OnCheckSplitView)
	EVT_MENU(idMENU_SELECT_AODIR,		Mainframe::OnSetAODir)
	EVT_MENU(idMENU_SELECT_HTML_COLOR,  Mainframe::OnSelectHtmlColor)
	EVT_MENU(idMENU_EXPORT_SCRIPT,		Mainframe::OnExportScriptToAo)
	EVT_MENU(idMENU_OPEN,				Mainframe::OnOpenProject)
	EVT_MENU(idMENU_SAVE,				Mainframe::OnSaveProject)
	EVT_MENU(idMENU_SAVE_AS,			Mainframe::OnSaveProjectAs)
	EVT_MENU(idMENU_NEW_PROJECT,		Mainframe::OnNewProject)
	EVT_MENU(idMENU_SHOW_PROJECT_PROPS, Mainframe::OnShowProjectProperties)
	EVT_MENU(idMENU_ADD_HTML_BREAKLINE, Mainframe::OnAddNewLine)
	EVT_MENU(idMENU_ADD_HTML_CENTERTEXT,Mainframe::OnAddCenterHtml)
	EVT_MENU(wxID_REDO,					Mainframe::OnRedo)
	EVT_MENU(wxID_UNDO,					Mainframe::OnUndo)
	EVT_MENU(idMENU_TOGGLE_WORDWRAP,    Mainframe::OnToggleWordWrap)
	EVT_MENU(idMENU_TOGGLE_LINENUMBERS, Mainframe::OnToggleLineNumbers)
	EVT_MENU(idMENU_SELECT_FONT,		Mainframe::OnSelectFont)
	EVT_MENU(idMENU_CHECK_VERSION,		Mainframe::OnCheckVersion)	
	EVT_MENU(idMENU_SETTINGS,			Mainframe::OnSettings)
	EVT_MENU(idMENU_SHOW_ICONBROWSER,   Mainframe::OnShowIconBrowser)
	EVT_MENU(idMENU_IMPORT_ICONS,       Mainframe::OnImportIcons)

	// wxStyled TextControl Events
	EVT_STC_MODIFIED(idPAGE_SOURCE,		Mainframe::OnHtmlEditModified)

	// Window Events
	EVT_CLOSE(Mainframe::OnClose)
END_EVENT_TABLE()
//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////
// Helper function to shorten errors
void wxErrorBox(const wxString& error, wxWindow* parent)
{
	wxMessageBox(error, wxMessageBoxCaptionStr, wxICON_ERROR|wxOK, parent);
}

void wxMessageBoxEx(const wxString& message, wxWindow* parent)
{
	wxMessageBox(message, wxMessageBoxCaptionStr, wxICON_INFORMATION|wxOK, parent);
}


//////////////////////////////////////////////////////////////////////////
// Constructor and Deconstructor
//////////////////////////////////////////////////////////////////////////
Mainframe::Mainframe(long style)
: wxFrame(NULL, -1, ASS_LABEL, wxDefaultPosition, wxSize(800,600), style),
  m_viewbase(NULL), m_project(NULL), m_icon_browser(NULL)
{
	// Create Config Object
	wxConfig* config = new wxConfig();

	// Create Status bar
	CreateStatusBar(2);

	// Read from config which view we want
	wxString view = config->Read("View", "Splitview");
	m_aodir = config->Read("AODir", "");

	// Create View first
	ChangeView(view);

	// Menu File
	wxMenu* mnuFile = new wxMenu;
	mnuFile->Append(idMENU_NEW_PROJECT, _("New Project...")+ wxT("\tCtrl-N"));
	mnuFile->AppendSeparator();
	mnuFile->Append(idMENU_OPEN, _("Open Project..") + wxT("\tCtrl-O"));	
	mnuFile->AppendSeparator();
	mnuFile->Append(idMENU_SAVE, _("Save Project")+ wxT("\tCtrl-S"));
	mnuFile->Append(idMENU_SAVE_AS, _("Save as..") + wxT("\tCtrl-Shift-S"));
	mnuFile->AppendSeparator();
	mnuFile->Append(idMENU_SHOW_PROJECT_PROPS, _("Project properties") + wxT("\tCtrl-P"));
	mnuFile->AppendSeparator();
	mnuFile->Append(idMENU_EXPORT_SCRIPT, _("Export Script..") + wxT("\tCtrl-E"));
	mnuFile->AppendSeparator();
	mnuFile->Append(idMENU_SELECT_AODIR, _("Set AODir.."));
	mnuFile->AppendSeparator();
	mnuFile->Append(idMENU_IMPORT_ICONS, _("Import Icons.."));
	mnuFile->AppendSeparator();
	mnuFile->Append(idMENU_EXIT, _("Exit") + wxT("\tCtrl-Q"));

	// Menu Edit
	wxMenu* mnuEdit = new wxMenu;
	mnuEdit->Append(wxID_UNDO, _("Undo"));
	mnuEdit->Append(wxID_REDO, _("Redo"));
	mnuEdit->AppendSeparator();
	mnuEdit->Append(idMENU_SETTINGS, _("Settings.."));
	mnuEdit->AppendSeparator();
	mnuEdit->AppendCheckItem(idMENU_TOGGLE_WORDWRAP, _("Word Wrap"));	
	mnuEdit->Check(idMENU_TOGGLE_WORDWRAP, m_viewbase->GetTextControl()->GetOptions().WordWrap);
	mnuEdit->AppendCheckItem(idMENU_TOGGLE_LINENUMBERS, _("Linenumbers"));
	mnuEdit->Check(idMENU_TOGGLE_LINENUMBERS, m_viewbase->GetTextControl()->GetOptions().LineNumbers);

	// Menu View
	wxMenu* mnuView = new wxMenu;
	mnuView->Append(idMENU_SELECT_FONT, _("Font.."));
	mnuView->AppendSeparator();
	mnuView->AppendRadioItem(idMENU_SPLITVIEW, _("Splitted View"));
	mnuView->AppendRadioItem(idMENU_NOTEBOOKVIEW, _("Tabbed View"));
	int id = (view == "Splitview" ? idMENU_SPLITVIEW : idMENU_NOTEBOOKVIEW);
	mnuView->Check(id, true);

	// Menu Snippets
	wxMenu* mnuSnippets = new wxMenu;
	mnuSnippets->Append(idMENU_SELECT_HTML_COLOR, _("Insert HTML Color") + wxT("\tAlt-C"));
	mnuSnippets->Append(idMENU_ADD_HTML_BREAKLINE, _("Insert HTML Linebreak") + wxT("\tAlt-N"));
	mnuSnippets->Append(idMENU_ADD_HTML_CENTERTEXT, _("Center HTML Text") + wxT("\tAlt-D"));
	mnuSnippets->AppendSeparator();
	mnuSnippets->Append(idMENU_SHOW_ICONBROWSER, _("Show IconBrowser...") + wxT("\tAlt-I"));

	// Menu Preview
	wxMenu* mnuPreview = new wxMenu;
	mnuPreview->Append(idMENU_RELOAD_HTML, _("Reload") + wxT("\tF5"));
	
	// Menu Help
	wxMenu* mnuHelp = new wxMenu;
	mnuHelp->Append(idMENU_SHOW_STARTUP, _("Manual") + wxT("\tF1"));
	mnuHelp->Append(idMENU_ABOUT, _("About...") + wxT("\tShift-F1"));
	mnuHelp->AppendSeparator();
	mnuHelp->Append(idMENU_CHECK_VERSION, _("Check for Updates") + ("\tF12"));

	// Append to Menu bar
	wxMenuBar* bar = new wxMenuBar();
	bar->Append(mnuFile, _("File"));
	bar->Append(mnuEdit, _("Edit"));
	bar->Append(mnuView, _("View"));
	bar->Append(mnuSnippets, _("Tools"));
	bar->Append(mnuPreview, _("Preview"));
	bar->Append(mnuHelp, _("?"));
	this->SetMenuBar(bar);

	// Check if AO Directory is set
	if ( m_aodir == "" )
	{
		wxString result = GetAnarchyDirectoryFromRegistry();
		if ( result.IsEmpty() )
		{
			wxErrorBox(_("You did not yet set the directory where Anarchy Online is installed to.\n"
						 "Please set your AO directory now."), this);

			wxCommandEvent e;
			e.SetEventObject(this);
			e.SetId(idMENU_SELECT_AODIR);
			e.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
			AddPendingEvent(e);
		}
		else
		{
			if ( wxMessageBox(_("I have found the Anarchy Online Directory in '") + result + "'.\n" + wxString(_("Do you want to use this path?")), 
							  wxMessageBoxCaptionStr, wxYES_NO, this) == wxYES )
			{
				config->Write("AODir", result);
				m_aodir = result;
			}
			else
			{
				wxCommandEvent e;
				e.SetEventObject(this);
				e.SetId(idMENU_SELECT_AODIR);
				e.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
				AddPendingEvent(e);
			}
		}


	}

	// Size Window to last Size
	int x = config->Read("LastWindowSizeX", 1024);
	int y = config->Read("LastWindowSizeY",  768);
	this->SetSize(wxSize(x, y));

	// Restore position
	int x_pos = config->Read("LastWindowPosX", -1);
	int y_pos = config->Read("LastWindowPosY", -1);

	if ( x_pos == -1 && y_pos == -1 )
	{
		this->CenterOnParent();
	}
	else
	{
		this->Move(wxPoint(x_pos, y_pos));
	}

	//Send Help Event to show help on startup
	wxCommandEvent cmdEvent;
	cmdEvent.SetEventObject(this);
	cmdEvent.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
	cmdEvent.SetId(idMENU_SHOW_STARTUP);
	ProcessEvent(cmdEvent);	

	// Delete Config
	delete config;
}

Mainframe::~Mainframe()
{
	// Write current Window Size to registry
	wxConfig* cfg = new wxConfig();
	
	cfg->Write("LastWindowSizeX", this->GetSize().GetX());
	cfg->Write("LastWindowSizeY", this->GetSize().GetY());

	cfg->Write("LastWindowPosX", this->GetPosition().x);
	cfg->Write("LastWindowPosY", this->GetPosition().y);

	delete cfg;

	delete m_viewbase;
	delete m_project;
}

void Mainframe::ChangeView( const wxString& view )
{
	wxString saved;

	// Freeze App
	this->Freeze();

	// Save content from source area
	if ( m_viewbase != NULL )
	{
		saved = m_viewbase->GetTextControl()->GetValue();	
	}	

	// Delete old view
	delete m_viewbase;

	// Recreate
	if ( view == wxT("Splitview"))
	{
		m_viewbase = new Splitview(this);
	}
	else if ( view == wxT("Notebookview"))
	{
		m_viewbase = new Notebookview(this);
	}

	// Set Maxsize for wxStyledTextCtrl	
	int max_size_mod = sizeof(char); // just in case sizeof(char) is not 1 on other os than win32
	m_max_textlength = ASS_MAX_SCRIPT_LENGTH / max_size_mod;
	m_viewbase->GetTextControl()->SetMaxLength(m_max_textlength);

	// Send Size Event
	wxSizeEvent sizeEvent;
	sizeEvent.SetEventObject(this);
	ProcessEvent(sizeEvent);

	// Set old content back
	m_viewbase->GetTextControl()->AppendText(saved);

	// Reload HTML
	wxCommandEvent cmdEvent;
	cmdEvent.SetEventObject(this);
	cmdEvent.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
	cmdEvent.SetId(idMENU_RELOAD_HTML);
	ProcessEvent(cmdEvent);

	// Unfreeze
	this->Thaw();
}


//////////////////////////////////////////////////////////////////////////
// Events
//////////////////////////////////////////////////////////////////////////

void Mainframe::OnExit( wxCommandEvent& )
{
	AskUserForSaveOnModifiedProject();
	this->Close(true);
}

void Mainframe::OnAbout( wxCommandEvent& )
{
	m_viewbase->GetHtmlWindow()->LoadFile(wxFileName("html/about.html"));
}

void Mainframe::OnReloadHtml( wxCommandEvent& )
{
	wxString source;
	source = wxT("<html><body bgcolor='#1a2733'>");
	source += m_viewbase->GetSourceText();
	source += wxT("</body></html>");

	m_viewbase->SetHtmlSource(source);
	SetStatusText(_("Reload Complete"), 0);
}

void Mainframe::OnShowStartup( wxCommandEvent& )
{
	wxFileName page(ASS_STARTUP_FILE + wxString(".") + wxGetApp().GetLanguage() + wxString(".html"));
	page.Normalize();
	m_viewbase->LoadHtmlPage(page.GetFullPath(wxPATH_WIN));	
}

void Mainframe::OnCheckNotebookView( wxCommandEvent& )
{
	wxConfig* config = new wxConfig();
	config->Write("View", "Notebookview");
	delete config;
	this->ChangeView("Notebookview");
}

void Mainframe::OnCheckSplitView( wxCommandEvent& )
{
	wxConfig* config = new wxConfig();
	config->Write("View", "Splitview");
	delete config;
	this->ChangeView("Splitview");
}

void Mainframe::OnSetAODir( wxCommandEvent& )
{
	wxString dir = wxDirSelector(_("Please select the Directory you installed Anarchy Online to"), m_aodir);
	if ( wxDir::Exists(dir) && !dir.empty() )
	{
		m_aodir = dir;
		wxConfig* config = new wxConfig();
		config->Write("AODir", m_aodir);
		delete config;
	}
}

void Mainframe::OnSelectHtmlColor( wxCommandEvent& )
{	
	wxColour chosen_color;

	// Try to get last color
	wxConfig* cfg = new wxConfig();
	wxString s_last = cfg->Read("LastHTMLColor", wxString("#FF0000"));
	wxColourData data;
	data.SetColour(wxColour(s_last));
	delete cfg;

	// Set last color
	chosen_color = wxGetColourFromUser(this, wxNullColour, _("Select a colour"), &data );
	
	if ( chosen_color.IsOk() )
	{
		// Save chosen color
		wxConfig* cfg = new wxConfig();
		cfg->Write("LastHTMLColor", chosen_color.GetAsString());
		delete cfg;

		HtmlEdit* ctrl = m_viewbase->GetTextControl();
		wxString selection = ctrl->GetStringSelection();
		if ( !selection.IsEmpty() )
		{
			long from = 0;
			long to = 0;
			ctrl->GetSelection(&from, &to);
			ctrl->Replace(from, to, "");
			ctrl->SetInsertionPoint(from);
			ctrl->WriteText(wxString("<font color=") + chosen_color.GetAsString(wxC2S_HTML_SYNTAX) + wxString(">") + selection + wxString("</font>"));
		}
		else
		{
			ctrl->WriteText(wxString("<font color=") + chosen_color.GetAsString(wxC2S_HTML_SYNTAX) + wxString("></font>"));
		}		
	}	
}

void Mainframe::OnExportScriptToAo( wxCommandEvent& )
{	
	// Check if AODir has been set
	if ( m_aodir.empty() )
	{
		wxMessageBox(_("You did not yet set the directory where Anarchy Online is installed to.\n"
					   "Please set your AO directory now and export again."),
					  wxMessageBoxCaptionStr, wxOK | wxCENTRE | wxICON_WARNING);
		wxMenuEvent e;
		e.SetEventObject(this);
		e.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
		e.SetId(idMENU_SELECT_AODIR);
		ProcessEvent(e);
		return;
	}

	// Check for project
	if ( m_project == NULL )
	{
		wxMessageBox(_("You did not yet create a Project. Please create one first"));
		return;
	}

	// Create Filename and normalize
	wxFileName fn(m_aodir + wxT("/scripts/"), m_project->GetCommandName());
	fn.Normalize();
	
	// Write File
	std::wofstream stream(fn.GetFullPath().wc_str());
	if ( stream.is_open() && stream.good() )
	{
		// Open Link
		stream << wxT("<a href=\"text://");

		// Get all lines and append into one big line.
		for (int i = 0; i < m_viewbase->GetTextControl()->GetNumberOfLines(); ++i )
		{
			wxString buffer = m_viewbase->GetTextControl()->GetLineText(i);
			buffer.Trim();
			buffer = buffer.BeforeFirst('\r');
			buffer = buffer.BeforeFirst('\n');
			wxString temp = DoRegExOnString(buffer);
			if ( temp.IsEmpty() )
			{
				stream << buffer.wc_str();
			}	
			else
			{
				stream << temp.wc_str();
			}
		}

		// Finish Link and close File
	    stream << wxT("\">");
	    stream << m_project->GetChatLinkName();
	    stream << wxT("</a>");
		stream.close();		

		SetStatusText(_("Script sucesfully exported to " + fn.GetFullPath()));
	}
	else
	{
		wxMessageBox(_("Cannot create specified file. Please check permissions in that directory."),
					 wxMessageBoxCaptionStr, 4|wxCENTRE|wxOK|wxICON_ERROR, this);
	}	
}

void Mainframe::OnOpenProject( wxCommandEvent& )
{
	if ( m_project != NULL )
	{
		if ( wxMessageBox(_("Do you want to save your current project?"), wxMessageBoxCaptionStr, wxYES_NO|wxCENTRE, this) == wxID_YES)
		{
			ProjectManager mgr;
			if ( !mgr.SaveProject(m_project, m_viewbase->GetTextControl()) )
			{
				wxErrorBox(_("Saving project failed!"), this);
			}
			else
			{
				SetStatusText("Project saved...", 0);				
			}
		}
	}

	// Clear current
	m_viewbase->GetTextControl()->ClearAll();
	wxDELETE(m_project);

	// Create Dialog
	wxFileDialog dlg(this, _("Please select the project to load"), wxFileName::GetCwd(), 
					 wxEmptyString, "*.proj", wxFD_OPEN | wxFD_FILE_MUST_EXIST);

	// Show Dialog and load stuff
	if ( dlg.ShowModal() == wxID_OK )
	{
		ProjectManager mgr;
		m_project = mgr.LoadProject(dlg.GetPath(), m_viewbase->GetTextControl());
		this->SetLabel(wxString(ASS_LABEL) + wxT(" | ") + _("Active Project: /") + m_project->GetCommandName());
		m_viewbase->GetTextControl()->EmptyUndoBuffer();
	}

	// Refresh Display
	wxCommandEvent e;
	e.SetEventObject(this);
	e.SetId(idMENU_RELOAD_HTML);
	e.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
	ProcessEvent(e);
}

void Mainframe::OnSaveProject( wxCommandEvent& )
{
	ProjectManager mgr;
	if ( m_project == NULL )
	{
		wxErrorBox(_("There is no project to save!"), this);
		return;
	}
	if ( !mgr.SaveProject(m_project, m_viewbase->GetTextControl()) )
	{
		wxErrorBox(_("Saving project failed!"), this);
	}
	else
	{
		SetStatusText("Project saved...", 0);
		m_viewbase->GetTextControl()->SetModified(false);
	}	
}

void Mainframe::OnSaveProjectAs( wxCommandEvent& )
{
	if ( m_project == NULL )
	{
		wxErrorBox(_("There is no project to save!"), this);
		return;
	}
	wxFileDialog dlg(this, _("Please select the file to save the project to"), wxFileName::GetCwd(), 
					 m_project->GetFileName(), "*.proj", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);

	if ( dlg.ShowModal() == wxID_OK )
	{
		// Get Chosen file
		wxFileName f = dlg.GetPath();

		// Save last directory
		wxConfig* conf = new wxConfig();
		conf->Write("LastDirectory", f.GetPath());
		delete conf;
		
		// Save
		ProjectManager mgr;
		if ( !mgr.SaveProjectAs(m_project, f.GetFullPath(), m_viewbase->GetTextControl()))
		{
			wxErrorBox(_("Saving project failed!"), this);
		}
		else
		{
			SetStatusText("Project saved...", 0);
			m_viewbase->GetTextControl()->SetModified(false);
		}
	}
}

void Mainframe::OnNewProject( wxCommandEvent& )
{
	// Create Dialog
	NewProjectDialog* dlg = new NewProjectDialog(this);

	AskUserForSaveOnModifiedProject();

	// Show dialog
	if ( dlg->ShowModal() == wxID_OK )
	{
		if ( dlg->GetChatCommand().IsEmpty() || dlg->GetChatLink().IsEmpty() )
		{
			wxErrorBox(_("Command and/or chatlink appears to be empty. Cannot create the project."), this);
		}
		else
		{
			// Get last directory
			wxString lastDir;
			wxConfig* conf = new wxConfig();
			lastDir = conf->Read("LastDirectory", wxFileName::GetCwd());
			delete conf;

			// Clear current
			m_viewbase->GetTextControl()->ClearAll();
			if ( m_project != NULL ) { delete m_project; }

			// Save project file
			wxFileDialog fDlg(this, _("Please select the file to save the project to"), lastDir, 
				wxEmptyString, "*.proj", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);

			if ( fDlg.ShowModal() == wxID_OK )
			{
				ProjectManager mgr;
				m_project = mgr.NewProject(dlg->GetChatCommand(), dlg->GetChatLink(), fDlg.GetPath());
				this->SetLabel(wxString(ASS_LABEL) + wxT(" | ") + _("Active Project: /") + m_project->GetCommandName());
				m_viewbase->GetTextControl()->EmptyUndoBuffer();
			}
		}
	}
	delete dlg;
}

void Mainframe::OnShowProjectProperties( wxCommandEvent& )
{
	if ( m_project != NULL )
	{
		// Create Dialog
		wxDialog* dlg = new ProjectPropertiesDialog(this, m_project, m_aodir);
		dlg->ShowModal();
		delete dlg;
	}
	else
	{
		wxErrorBox(_("There is no active project"), this);
	}
}

void Mainframe::OnAddNewLine( wxCommandEvent& )
{
	HtmlEdit* txt = m_viewbase->GetTextControl();
	txt->WriteText("<br>");
}

void Mainframe::OnAddCenterHtml( wxCommandEvent& )
{
	HtmlEdit* ctrl = m_viewbase->GetTextControl();
	wxString selection = ctrl->GetStringSelection();
	if ( !selection.IsEmpty() )
	{
		long from = 0;
		long to = 0;
		ctrl->GetSelection(&from, &to);
		ctrl->Replace(from, to, "");
		ctrl->SetInsertionPoint(from);
		ctrl->WriteText(wxString("<div align=center>") + selection + wxString("</div>"));
	}
	else
	{
		ctrl->WriteText(wxString("<div align=center></div>"));
	}		
}

void Mainframe::OnShowIconBrowser( wxCommandEvent& )
{
	if ( m_icon_browser == NULL )
	{
		m_icon_browser = new IconBrowser(this);
	}
	m_icon_browser->Show(!m_icon_browser->IsShown());
}

void Mainframe::OnUndo( wxCommandEvent& )
{
	if ( m_viewbase->GetTextControl()->CanUndo() )
	{
		m_viewbase->GetTextControl()->Undo();
	}	
}

void Mainframe::OnRedo( wxCommandEvent& )
{
	if (m_viewbase->GetTextControl()->CanRedo())
	{
		m_viewbase->GetTextControl()->Redo();
	}
}

void Mainframe::OnToggleWordWrap( wxCommandEvent& e )
{
	m_viewbase->GetTextControl()->SetWordWrap(!m_viewbase->GetTextControl()->GetOptions().WordWrap);
}

void Mainframe::OnSelectFont( wxCommandEvent& e )
{
	wxFont fnt(m_viewbase->GetTextControl()->GetOptions().Font);	
	fnt = wxGetFontFromUser(this, fnt);
	if ( fnt.IsOk() )
	{
		m_viewbase->GetTextControl()->SetNewFont(fnt);
	}	
}

void Mainframe::TellVersion( wxString v )
{
	v.Trim();

	wxStringTokenizer tokens(v, ".");
	wxString s_major = tokens.GetNextToken();
	wxString s_minor = tokens.GetNextToken();
	wxString s_patch = tokens.GetNextToken();

	Version version;

	{
		std::wstringstream ss(s_major.wc_str());
		ss >> version.major;
	}
	{
		std::wstringstream ss(s_minor.wc_str());
		ss >> version.minor;
	}
	{
		std::wstringstream ss(s_patch.wc_str());
		ss >> version.patch;
	}

	if ( ASS_VERSION >= version )
	{
		wxMessageBoxEx(wxString(_("You already have the newest version:")) + " " + v, this);
	}
	else
	{
		if ( wxMessageBox(_("Newer version available:") + " " + v + "\n" + wxString(_("Do you want to go to the downloadpage?")), 
			   		      wxMessageBoxCaptionStr, wxYES_NO, this) == wxYES )
		{
			wxLaunchDefaultBrowser("http://code.google.com/p/awesomescript/downloads/list");
		}
	}
}

void Mainframe::OnToggleLineNumbers( wxCommandEvent& )
{
	m_viewbase->GetTextControl()->ShowLineNumbers(!m_viewbase->GetTextControl()->GetOptions().LineNumbers);
}

void Mainframe::OnHtmlEditModified( wxStyledTextEvent& )
{
	int chatlinksize = 0;

	// Get chatlinksize
	if ( m_project )
	{
		chatlinksize = (m_project->GetChatLinkName().length() * sizeof(char));
	}

	// Current Size is the Text, the Tags that follow and the chatlink
	int cur = m_viewbase->GetTextControl()->GetTextLength() 
					+ (ASS_STATIC_SCRIPT_TEXT.length() * sizeof(char))
					+ chatlinksize;
	wxString status;
	status << _("Script Length:") << " " << cur << "/" << m_max_textlength;

	this->SetStatusText(status, 1);
	if ( cur > m_max_textlength )
	{
		// TODO: Prevent Input
	}
}

void Mainframe::OnSettings( wxCommandEvent& )
{
	SettingsDialog dlg(this, m_viewbase->GetTextControl());
	int result = dlg.ShowModal();
	if ( result == wxID_OK )
	{
		dlg.Save();
	}
}

void Mainframe::AskUserForSaveOnModifiedProject()
{
	if ( m_viewbase->GetTextControl()->IsModified() )
	{
		if (wxMessageBox(_("The source code is modified. Do you want to save your changes?"), wxMessageBoxCaptionStr,
			    	     wxYES_NO, this) == wxYES )
		{
			if ( m_project != NULL )
			{
				wxCommandEvent e;
				e.SetId(idMENU_SAVE);
				e.SetEventObject(this);
				e.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
				ProcessEvent(e);
			}
		}
	}
}

void Mainframe::OnClose( wxCloseEvent& e)
{
	AskUserForSaveOnModifiedProject();
	e.Skip();
}

void Mainframe::InsertIcon( const wxString& display )
{
	m_viewbase->GetTextControl()->WriteText(display);
}

void Mainframe::OnImportIcons( wxCommandEvent& )
{
	wxDirDialog dlg(this, _("Please select the folder.."), wxEmptyString, wxDD_DIR_MUST_EXIST);
	if ( dlg.ShowModal() == wxID_OK )
	{
		if ( !wxDirExists("icons") )
		{
			wxMkDir("icons");
			if ( !wxDirExists("icons") )
			{
				wxErrorBox(_("Cannot write to my directory! Abort."), this);
				return;
			}
		}
		IconBrowser::DoSortImages(this, dlg.GetPath(), "icons");
	}
}

wxString Mainframe::DoRegExOnString( wxString& text )
{	
	wxRegEx RegEx("<img src=[^>]*>");

	if ( RegEx.Matches(text) )
	{
		wxString result = wxEmptyString;	
		int count = RegEx.GetMatchCount();
		for ( int i = 0; i < count; i ++ )
		{
			wxString raw = RegEx.GetMatch(text, i);

			// Get the path
			int start = raw.find_first_of('=') + 1;
			int end = raw.find_last_of('>') - 1;
			wxString file = raw.SubString(start, end);

			// Extract iconnumber
			wxString new_file = file.SubString(file.find_last_of('/')+1, file.find_last_of('.') - 1);
			new_file.Prepend("rdb://");
			text.Replace(file, new_file);
			return text;
		}
	}
	return wxEmptyString;
}

void Mainframe::OnCheckVersion( wxCommandEvent& )
{	
	CURL* curl = curl_easy_init();
	curl_easy_setopt(curl, CURLOPT_URL, "http://awesomescript.googlecode.com/svn/trunk/ass_version.txt");
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_curl_write);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
	if ( curl_easy_perform(curl) != CURLE_OK ) 
	{
		wxErrorBox(_("Could not connect to server. Please check Firewall or try later."), this);
	}
	curl_easy_cleanup(curl);	
}


// This works pretty straigth: Tries to read the install dir set by anarchies client on win32. 
// If not found, it returns an empty string. On all other platforms it returns an empty string only,
// so we simply check for the string empty or not in the constructor.
wxString Mainframe::GetAnarchyDirectoryFromRegistry()
{
	wxString result = wxEmptyString;
#ifdef WIN32	
	wxRegKey* regKey = new wxRegKey("HKEY_CURRENT_USER\\Software\\Anarchy Online");
	if ( regKey->Exists() )
	{
		wxString temp;
		if ( regKey->QueryValue("Install Directory", temp) )
		{
			result = temp;
		}
	}
	delete regKey;	
#endif /* WIN32 */

	return result;
}
